package com.example.nick.bodyapplication.widget

import android.content.Context
import android.content.res.Resources
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.widget.ScrollView
import android.widget.Toast
import kotlin.math.ceil


class WeekDayTabView : View {

    val _dayCount = 7
    val _hourCount = 24

    var weekDayArr = Array(size = _dayCount, init = { Array(_hourCount, init = { 0 }) })
    val dayArr = Array(size = _hourCount, init = { 0 })

    var itemWidth = 0.0f
    var itemHeight = 0.0f
    val itemHeightScalc = 0.60f

    /**
     * 最左边时间line width 为 item * 0.57
     * Time line width
     */
    val timeLineScalc = 0.5747f
    var timeLineWidth = 0.0f
    var timeLineHeight = 0.0f

    var weekHeight = 0.0f

    var paintLine = Paint(Paint.ANTI_ALIAS_FLAG)
    var paintTime = Paint(Paint.ANTI_ALIAS_FLAG)
    var paintTextWeek = Paint(Paint.ANTI_ALIAS_FLAG)
    var paintRect = Paint(Paint.ANTI_ALIAS_FLAG)

    val spaceSize = 7
    val spaceSizeY = 7

    var curRow = 0
    var curColumn = 0
    var moveRow = 0
    var moveColumn = 0

    var scrollView: ScrollView? = null

    constructor(ctx: Context) : super(ctx, null)
    constructor(ctx: Context, attrs: AttributeSet) : this(ctx, attrs, 0)
    constructor(ctx: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
        ctx,
        attrs,
        defStyleAttr
    ) {
        initAttrs(ctx, attrs)
    }

    private fun initAttrs(ctx: Context, attrs: AttributeSet) {
        //
        paintLine.color = Color.BLACK
        paintLine.strokeWidth = 0.5f
        paintTime.color = Color.BLACK
        paintTime.textSize = dp2px(9.33f).toFloat()
        paintTextWeek.color = Color.BLACK
        paintTextWeek.textSize = dp2px(12f).toFloat()
        paintTextWeek.style = Paint.Style.FILL
        paintTextWeek.textAlign = Paint.Align.CENTER
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        var v_w = measureWidth(widthMeasureSpec)
        itemWidth = (v_w - 2 * spaceSize) / (_dayCount + timeLineScalc)
        itemHeight = itemWidth * itemHeightScalc
        timeLineWidth = itemWidth * timeLineScalc
        timeLineHeight = timeLineWidth * 0.7123f
        weekHeight = itemHeight * 1.4588f
        var v_h = weekHeight + itemHeight * _hourCount + 2 * spaceSize
        setMeasuredDimension(v_w, ceil(v_h.toDouble()).toInt())
    }

    private fun measureWidth(measureSpec: Int): Int {
        val specMode = MeasureSpec.getMode(measureSpec)
        val specSize = MeasureSpec.getSize(measureSpec)
        //设置一个默认值，就是这个View的默认宽度为500，这个看我们自定义View的要求
        var result = 500
        if (specMode == MeasureSpec.AT_MOST) {//相当于我们设置为wrap_content
            result = specSize
        } else if (specMode == MeasureSpec.EXACTLY) {//相当于我们设置为match_parent或者为一个具体的值
            result = specSize
        }
        Log.i(
            "v_t",
            "v_t measureWidth AT_MOST:${MeasureSpec.AT_MOST}, EXACTLY:${MeasureSpec.EXACTLY}, UNSPECIFIED:${MeasureSpec.UNSPECIFIED}"
        )
        Log.i("v_t", "v_t measureWidth specMode:$specMode, specSize:$specSize")
        return result
    }

    override fun onDraw(canvas: Canvas) {
//        itemWidth = width.toFloat() / (7 + timeLineScalc)
//        itemHeight = itemWidth * itemHeightScalc
//        timeLineWidth = itemWidth * timeLineScalc
//        timeLineHeight = timeLineWidth * 0.7123f
//        weekHeight = itemHeight * 1.4588f

        canvas.save()
        drawWeekTop(canvas)
        drawDay(canvas)
        drawRectLine(canvas)
        drawTimeLine(canvas)
        canvas.restore()
    }

    private fun drawRectLine(canvas: Canvas) {
        // 绘制竖线
        Log.i("v_t", "v_t width:$width, height:$height")
        val rowXStart = timeLineWidth + spaceSize
        val rowXEnd = width.toFloat() - spaceSize
        val columnYStart = spaceSize.toFloat()
        val columnYEnd = height.toFloat() - spaceSize
        for (i in 0.._dayCount) {
            var lineX = rowXStart + i * itemWidth
            Log.d(
                "v_t",
                "v_t lineX:$lineX, timeLineWidth:$timeLineWidth, itemWidth:$itemWidth, itemHeith:$itemHeight"
            )
            canvas.drawLine(
                lineX,
                columnYStart,
                lineX,
                columnYEnd,
                paintLine
            )
        }

        // 绘制横线
        canvas.drawLine(rowXStart, spaceSize.toFloat(), rowXEnd, spaceSize.toFloat(), paintLine)
        for (i in 0.._hourCount) {
            var lineY = weekHeight + i * itemHeight + spaceSize
//            Log.i(
//                "v_t",
//                "v_t lineY:$lineY, timeLineWidth:$timeLineWidth, itemWidth:$itemWidth, itemHeith:$itemHeight"
//            )
            canvas.drawLine(
                rowXStart,
                lineY,
                rowXEnd,
                lineY,
                paintLine
            )
        }
    }

    private fun drawDay(canvas: Canvas) {
        val rowXStart = timeLineWidth + spaceSize
        val columnYStart = weekHeight + spaceSize.toFloat()

        weekDayArr.forEachIndexed { i, day ->
            day.forEachIndexed { j, hour ->
                paintRect.color = if (hour == 1) Color.RED else Color.BLUE
                canvas.drawRect(
                    rowXStart + i * itemWidth,
                    columnYStart + j * itemHeight,
                    rowXStart + (i + 1) * itemWidth,
                    columnYStart + (j + 1) * itemHeight,
                    paintRect
                )
            }
        }
    }

    private fun drawTimeLine(canvas: Canvas) {
        var textHeight = dp2px(9.33f)
        for (i in 0.._hourCount) {
            canvas.drawText(
                "$i:00",
                spaceSize.toFloat(),
                weekHeight + i * itemHeight + textHeight / 2,
                paintTime
            )
        }
    }

    private fun drawWeekTop(canvas: Canvas) {
        paintTextWeek.textSize = dp2px(12f).toFloat()
        val rowXStart = timeLineWidth + spaceSize
        val columnYStart = spaceSize.toFloat()
        for (i in 0..6) {
            //矩形背景
            val bgRect = Paint()
            bgRect.style = Paint.Style.FILL
            bgRect.color = Color.TRANSPARENT
            val rectF = RectF(
                rowXStart + i * itemWidth,
                columnYStart,
                rowXStart + (i + 1) * itemWidth,
                columnYStart + weekHeight
            )
            canvas.drawRect(rectF, bgRect)
            val text = "周$i"
            //计算baseline
            val fontMetrics = paintTextWeek.fontMetrics
            val distance = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom
            val baseline = rectF.centerY() + distance
            canvas.drawText(text, rectF.centerX(), baseline, paintTextWeek)
        }
    }

    fun updateArrays(arr: Array<Array<Int>>) {
        weekDayArr = arr
        invalidate()
    }

    var downTime = 0L
    var cruiseFlag = 0b00
    val cruiseValueHor = 0b01

    //    val cruiseValuePsp = 0b10
    var use6hour = false

    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                downTime = System.currentTimeMillis()
                //scrollView?.requestDisallowInterceptTouchEvent(true)
            }
//            MotionEvent.ACTION_MOVE -> {
//                val (r, c) = getRowColumn(event.x, event.y)
//                Log.i(
//                    "area",
//                    "area move x:${event.x}, y:${event.y}, r:$r, c:$c, curRow:$curRow, curColumn:$curColumn"
//                )
//                if (r == -1 || c == -1 || c != curColumn || (moveColumn == c)) {
//                    return true
//                }
//                if (curRow != r) {
//                    moveRow = r
//                    moveColumn = c
//                    dealTouchMove(r, c)
//                    invalidate()
//                }
//            }
            MotionEvent.ACTION_UP -> {
//                scrollView?.requestDisallowInterceptTouchEvent(false)
                // 触摸超过200ms就认为是长按
                if (System.currentTimeMillis() - downTime > 200) {
                    return true
                }
                val (r, c) = getRowColumn(event.x, event.y)
                if (r == -1 || c == -1) {
                    return true
                }

                curRow = r
                curColumn = c
                Log.i(
                    "v_t",
                    "v_t down x:${event.x}, y:${event.y}, r:$r, c:$c, scrollY:${scrollView?.scrollY}, scrollView.h:${scrollView?.height}"
                )
                if (dealItemCheck(r, c)) {
                    invalidate()
                } else {
                    val msg = if (use6hour) "Click 6 Error" else "Click 4 Error"
                    Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
                }
            }
        }
        return true
    }

    private fun dealItemCheck(r: Int, c: Int): Boolean {


        if (use6hour) {
            if (weekDayArr[c][r] != 0) {
                weekDayArr[c][r] = 0
                return true
            }
            var count = _hourCount
            var left = r - 1
            var right = r + 1
            var canLeft = true
            var canRight = true
            var sum = 0
            var changeCRight = c
            var changeCLeft = c
            while (--count > 0) {
                if (canRight) {// 向后计算
                    if (changeCRight in 0 until _dayCount) {
                        if (right <= _hourCount - 1) {
                            if (weekDayArr[changeCRight][right] == 0) {
                                canRight = false
                            } else {
                                sum += 1
                            }
                            Log.i(
                                "v_t",
                                "v_t weekDayArr[$changeCRight][$right]:${weekDayArr[changeCRight][right]}, canRight:$canRight, sum:$sum"
                            )
                            right += 1
                        } else if (changeCRight == c && right == _hourCount) { // 跨天处理
                            changeCRight = if (c == 6) 0 else c + 1 // 周7与周6，列的切换
                            right = 0
                            if (weekDayArr[changeCRight][right] == 0) {
                                canRight = false
                            } else {
                                sum += 1
                                right += 1
                            }
                            Log.i(
                                "v_t",
                                "v_t other weekDayArr[$changeCRight][$right]:${weekDayArr[changeCRight][right]}, canRight:$canRight, sum:$sum"
                            )
                        }
                    }
                }

                if (canLeft) {// 向前计算
                    if (changeCLeft in 0 until _dayCount) {
                        if (left >= 0) {
                            if (weekDayArr[changeCLeft][left] == 0) {
                                canLeft = false
                            } else {
                                sum += 1
                            }
                            Log.i(
                                "v_t",
                                "v_t weekDayArr[$changeCLeft][$left]:${weekDayArr[changeCLeft][left]}, canLeft:$canLeft, sum:$sum"
                            )
                            left -= 1
                        } else if (changeCLeft == c && left == -1) { // 跨天处理
                            changeCLeft = if (c == 0) 6 else c - 1 // 周6与周7，列的切换
                            left = _hourCount - 1
                            if (weekDayArr[changeCLeft][left] == 0) {
                                canLeft = false
                            } else {
                                sum += 1
                                left -= 1
                            }
                            Log.i(
                                "v_t",
                                "v_t other weekDayArr[$changeCLeft][$left]:${weekDayArr[changeCLeft][left]}, canLeft:$canLeft, sum:$sum"
                            )
                        }
                    }
                }

                Log.i(
                    "v_t",
                    "v_t count:$count, sum:$sum, canRight:$canRight, canLeft:$canLeft"
                )

                if (!canRight && !canLeft) {
                    break
                }

                if (sum >= 6) { // 不能连续6个小时
                    return false
                }
            }
            weekDayArr[c][r] = cruiseValueHor
            return true
        } else {
            // 思路1：计算分割模块
            /*for (i in 0..23) {
                dayArr[i] = weekDayArr[c][i]
            }
            dayArr[r] = if (dayArr[r] == cruiseValueHor) 0 else cruiseValueHor
            var count = 0
            var index = -2
            for (i in 0..23) {
                val v = dayArr[i]
                if (v == 0) {
                    if (i - index > 1) {
                        count++
                    }
                    index = i
                }
            }
            Log.i(
                "v_t",
                "v_t count:$count, index:$index"
            )
            if (dayArr[0] == cruiseValueHor && dayArr[23] == cruiseValueHor && count > 3) {
                return false
            } else if ((dayArr[0] == cruiseValueHor || dayArr[23] == cruiseValueHor) && count > 4) {
                return false
            } else if (count > 5) {
                return false
            }
            weekDayArr[c][r] = dayArr[r]
            return true*/

            // 思路2，计算选中模块
            for (i in 0..23) {
                dayArr[i] = weekDayArr[c][i]
            }
            dayArr[r] = if (dayArr[r] == cruiseValueHor) 0 else cruiseValueHor
            var count = 0
            var index = -2
            for (i in 0..23) {
                val v = dayArr[i]
                if (v == cruiseValueHor) {
                    if (i - index > 1) {
                        count++
                    }
                    index = i
                }
            }
            Log.i(
                "v_t",
                "v_t count:$count, index:$index"
            )
            if (count > 4) {
                return false
            }
            weekDayArr[c][r] = dayArr[r]
            return true
        }
    }

    private fun dealTouchMove(r: Int, c: Int) {
        if (weekDayArr[c][r] == 1) {
            weekDayArr[c][r] = 0
        } else {
            weekDayArr[c][r] = 1
        }
    }

    fun getRowColumn(touchX: Float, touchY: Float): Pair<Int, Int> {
        val rowXStart = timeLineWidth + spaceSize
        val columnYStart = weekHeight + spaceSize.toFloat()

        var r = ((touchY - columnYStart) / itemHeight).toInt()
        var c = ((touchX - rowXStart) / itemWidth).toInt()

        if (r >= _hourCount || c >= 6) {
            Log.e(
                "area",
                "area error r:$r, c:$c, touchY:$touchY, touchX:$touchX, itemHeight:$itemHeight, itemWidth:$itemWidth, height:$height, width:$width"
            )
        }

        if (r >= 23) {
            r = 23
        }

        if (c >= 6) {
            c = 6
        }

        return Pair(r, c)
    }

    fun dp2px(dpValue: Float): Int {
        return (0.5f + dpValue * Resources.getSystem().displayMetrics.density).toInt()
    }
}